<template xmlns:input="http://www.w3.org/1999/html">
  <div style="display: inline-block;width: 100%">
    <div style="margin-bottom: 5px;background-color: rgba(128,128,128,0.1);padding: 5px 5px;border-radius: 5px;width: 100%" v-if="typeof(ldata)=='undefined'">
      <p style="color: rgb(128,128,128);font-size: 12px;font-weight: bold">Undefined</p>
    </div>
    <div style="margin-bottom: 5px;background-color: rgba(255,0,0,0.2);padding: 5px 5px;border-radius: 5px;width: 100%" v-if="typeof(ldata)=='boolean'">
      <p style="color: red;font-size: 12px;font-weight: bold">Boolean</p>
      <p v-if="ldata" style="color: black;font-size: 12px" @click="ldata = false">True</p>
      <p v-if="!ldata" style="color: black;font-size: 12px" @click="ldata = true">False</p>
    </div>
    <div style="margin-bottom: 5px;background-color: rgba(0,120,215,0.1);padding: 5px 5px;border-radius: 5px;width: 100%" v-if="typeof(ldata)=='number'">
      <p style="color: rgb(0,120,215);font-size: 12px;font-weight: bold">Number</p>
      <input :disabled="readOnly==true" @input="dataUpdated" v-model="ldata" style="line-height: 30px;width: 100%" type="number">
    </div>
    <div class="string-title" style="margin-bottom: 5px;background-color: rgba(71, 186, 134,0.1);padding: 5px 5px;border-radius: 5px;width: calc(100% + 0px)" v-if="typeof(ldata)=='string'">
      <p style="color: rgb(51, 134, 97);font-size: 12px;font-weight: bold;">
        <span>String</span>
        <span @click="toInt" v-if="isValueCanParseInt(ldata)==true && readOnly==false" class="to-int" style="padding: 0 5px;background-color: rgb(0,120,215);font-weight: bold;border-radius: 5px;margin-left: 5px;">To Number</span>
      </p>
      <textarea :disabled="readOnly==true" @input="dataUpdated" v-model="ldata" style="width: 100%"></textarea>
    </div>
    <div style="margin-bottom: 5px;border-radius: 5px;width: 100%;position: relative" v-if="typeof(ldata)=='object' && Array.isArray(ldata)==false"
      :style="{
          top:objectShow==true?'0px':'-2px'
      }"
    >
      <p style="color: rgb(204, 148, 6);font-size: 12px;font-weight: bold;background-color: rgba(255, 186, 8,0.1);border-radius: 5px;padding-left: 5px;padding-right: 55px;position: relative"
        :style="{
          paddingRight:objectShow==true?'95px':'55px',
        }"
      >JSON({{ Object.keys(ldata).length}})
        <div v-if="objectShow && readOnly==false" style="display: inline-block;position: absolute;right: 60px" @click="jsonShowAdd = !jsonShowAdd;">
          Add
        </div>
        <div v-if="jsonShowAdd" style="position: absolute;padding: 5px 5px;border-radius: 5px;display: inline-block;box-shadow: 0 4px 10px rgba(0,0,0,0.1);top: 15px;background-color: white;z-index: 1000">
          <p>setKeyValue</p>
          <input v-model="inputNewKeyName" placeholder="keyName" style="font-weight: unset" type="text" />
          <span style="color: red">{{ warningText }}</span><br>
          <span>valueType:</span>
          <select v-model="inputNewKeyType">
            <option>Number</option>
            <option>String</option>
            <option>Array</option>
            <option>JSON</option>
          </select><br>
          <button style="margin-right: 10px" @click="jsonAddOK">OK</button>
          <button @click="jsonShowAdd=false;warningText = '';inputNewKeyName='';inputNewKeyType='Number'">Cancel</button>
        </div>
        <div style="display: inline-block;position: absolute;right: 5px" @click="()=>{
          objectShow = !objectShow
          jsonShowAdd=false
        }">{{objectShow?'Collapse':'Expand'}}</div>
      </p>
      <div v-if="objectShow" v-for="item in Object.keys(ldata)" style="width: 100%;border-radius: 5px;padding-left: 20px">
        <span class="key" style="color: rgb(204, 148, 6);font-size: 12px;font-weight: bold;background-color: rgba(255, 186, 8,0.1);border-radius: 5px;padding: 0 5px">{{item}}:</span>
        <span v-if="readOnly==false" class="delete" style="font-size: 12px;font-weight: bold;padding: 0 5px;margin-left: 5px" @click="jsonDeleteKey(item)">Delete</span>
        <br>
        <span><data-editor :read-only="readOnly" @dataChanged="objectDataChanged" :data="ldata[item]" :key-name-or-index="item"></data-editor></span>
      </div>
    </div>
    <div style="margin-bottom: 5px;width: 100%;position: relative" v-if="typeof(ldata)=='object' && Array.isArray(ldata)==true"
         :style="{
            top:objectShow==true?'0px':'-2px'
         }"
    >
      <p style="color: rgb(112, 80, 166);font-size: 12px;font-weight: bold;background-color: rgba(112, 80, 166,0.1);border-radius: 5px;padding-left: 5px;padding-right: 55px;position: relative"
         :style="{
          paddingRight:objectShow==true?'95px':'55px',
        }"
      >Array({{ ldata.length }})
        <div style="display: inline-block;position: absolute;right: 5px;" @click="()=>{
          objectShow = !objectShow
        }">{{objectShow?'Collapse':'Expand'}}</div>
        <div v-if="objectShow && readOnly==false" style="display: inline-block;position: absolute;right: 60px" @click="arrayShowAdd = !arrayShowAdd;">
          Add
        </div>
        <div v-if="arrayShowAdd" style="position: absolute;padding: 5px 5px;border-radius: 5px;display: inline-block;box-shadow: 0 4px 10px rgba(0,0,0,0.1);top: 15px;background-color: white;z-index: 1000">
          <p>addValue</p>
          <span>valueType:</span>
          <select v-model="inputNewKeyType">
            <option>Number</option>
            <option>String</option>
            <option>Array</option>
            <option>JSON</option>
          </select><br>
          <button style="margin-right: 10px" @click="arrayAddOK">OK</button>
          <button @click="arrayShowAdd=false;inputNewKeyType='Number'">Cancel</button>
        </div>
      </p>
      <div v-if="objectShow" v-for="item in Object.keys(ldata)" style="width: 100%;padding-left: 20px">
        <span style="color: rgb(112, 80, 166);font-size: 12px;font-weight: bold;background-color: rgba(112, 80, 166,0.1);border-radius: 5px;padding: 0 5px">[{{item}}]</span>
        <span v-if="readOnly==false" class="delete" style="font-size: 12px;font-weight: bold;padding: 0 5px;margin-left: 5px" @click="arrDeleteItem(parseInt(item))">Delete</span>
        <br>
        <span><data-editor :read-only="readOnly" @dataChanged="objectDataChanged" :data="ldata[item]" :key-name-or-index="item"></data-editor></span>
      </div>
    </div>
  </div>
</template>

<script>
import dataEditor from './dataEditor.vue'

export default {
  name: '',
  data() {
    return {
      ldata:undefined,
      objectShow:false,
      jsonShowAdd:false,
      warningText:'',
      inputNewKeyName:'',
      inputNewKeyType:'Number',
      arrayShowAdd:false,
    }
  },

  methods: {
    toInt(){
      this.ldata = parseInt(this.ldata)
    },
    isValueCanParseInt(ldata){
      let t = ldata
      if(t==''){
        return false
      }
      t = t.split('')
      let i = 0
      if(t[0]=='-'){
        i=1
      }
      for(i;i<t.length;i++){
        t[i] = t[i].charCodeAt(0)
        if(!(t[i]>=48 && t[i]<=57)){
          return false
        }
      }
      return true
    },
    arrayAddOK(){
      switch (this.inputNewKeyType) {
        case 'Number':
          this.ldata.push(0)
          break
        case 'String':
          this.ldata.push('')
          break
        case 'Array':
          this.ldata.push([])
          break
        case 'JSON':
          this.ldata.push({})
          break
      }
      this.arrayShowAdd = false
      this.$emit('dataChanged',{
        data:this.ldata,
        keyNameOrIndex:this.keyNameOrIndex
      })
    },
    arrDeleteItem(index){
      let re = []
      for(let i=0;i<this.ldata.length;i++){
        if(i==index){
          continue
        }
        re.push(this.ldata[i])
      }
      this.ldata = []
      setTimeout(()=>{
        this.ldata = re
      },0.1)
    },
    jsonDeleteKey(key){
      let re = {

      }
      for(let i=0;i<Object.keys(this.ldata).length;i++){
        if(Object.keys(this.ldata)[i]==key){
          continue
        }
        re[Object.keys(this.ldata)[i]] = this.ldata[Object.keys(this.ldata)[i]]
      }
      this.ldata = {}
      setTimeout(()=>{
        this.ldata = re
        this.$emit('dataChanged',{
          data:this.ldata,
          keyNameOrIndex:this.keyNameOrIndex
        })
      },1)

    },
    jsonAddOK(){
      this.warningText = ''
      if(this.checkString(this.inputNewKeyName)==false){
        this.warningText = 'Invalid key format.'
        return
      }
      for(let i=0;i<Object.keys(this.ldata).length;i++){
        if(Object.keys(this.ldata)[i]==this.inputNewKeyName){
          this.warningText = 'Key already in use.'
          return
        }
      }
      switch (this.inputNewKeyType) {
        case 'Number':
          this.ldata[this.inputNewKeyName] = 0
          break
        case 'String':
          this.ldata[this.inputNewKeyName] = ''
          break
        case 'Array':
          this.ldata[this.inputNewKeyName] = []
          break
        case 'JSON':
          this.ldata[this.inputNewKeyName] = {}
          break
      }
      let t = JSON.parse(JSON.stringify(this.ldata))
      this.ldata = {}
      setTimeout(()=>{
        this.ldata = t
        this.$emit('dataChanged',{
          data:this.ldata,
          keyNameOrIndex:this.keyNameOrIndex
        })
        this.inputNewKeyName = ''
        this.jsonShowAdd = false
      },1)
    },
    dataUpdated(){
        this.$emit('dataChanged',{
          data:this.ldata,
          keyNameOrIndex:this.keyNameOrIndex
        })
    },
    objectDataChanged(data){
      this.ldata[data.keyNameOrIndex] = data.data
      this.$emit('dataChanged',{
        data:this.ldata,
        keyNameOrIndex:this.keyNameOrIndex
      })
    },
    checkString(string){
      if(string.length==0){
        return false
      }
      string = string.split('')
      for(let i=0;i<string.length;i++){
        if(string[i]=='-'){
          continue
        }
        string[i] = string[i].charCodeAt(0)
        if(string[i]>=48 && string[i]<=57){
          continue
        }
        if(string[i]>=65 && string[i]<=90){
          continue
        }
        if(string[i]>=97 && string[i]<=122){
          continue
        }
        return false
      }
      return true
    }
  },

  //生命周期 - 挂载完成（可以访问DOM元素）",html模板已渲染
  mounted() {
    this.ldata = this.data
  },

  components:{
    dataEditor
  },

  props: {
    data:undefined,
    keyNameOrIndex:undefined,
    readOnly:{
      default:false,
    }
  },

  //监听属性 类似于data概念",
  computed: {},

  //监控data中的数据变化",
  watch: {},

  //生命周期 - 创建完成（可以访问当前this实例）",数据模型已加载，方法已加载,html模板已加载,html模板未渲染
  created() {
  },

  //生命周期 - 挂载之前",html模板未渲染
  beforeMount() {
  },

  //生命周期 - 更新之前",数据模型已更新,html模板未更新
  beforeUpdate() {
  },

  // 生命周期 - 销毁之前调用
  beforeDestroy() {
  },

  //生命周期 - 更新之后",数据模型已更新,html模板已更新
  updated() {
  },

  //生命周期 - 销毁完成"
  destroyed() {
  },

  //如果页面有keep-alive缓存功能，这个函数会触发",
  activated() {
  }
}
</script>

<style>

.to-int{
  display: none;
  color: white;
}

.string-title:hover .to-int{
  display: unset;
}

.delete{
  color: gray;
  background-color: rgba(0,0,0,0.1);
  border-radius: 5px;
}

</style>